package org.jdk.learning.stream;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author xin
 * @version 1.0
 */
public class StreamOpDemo {


    public static void main(String[] args) {
        List<Dish> menu = init();
        //
        menu.stream()
                //筛选 Predicate<Dish>
                .filter(d -> d.getCalories() < 400)
                //排序：sorted的参数是Comparator<Dish>, comparing方法返回一个Comparator实例，
                // 使用Function<Dish,Integer>来转换
                //传统方法是new Comparator<Dish>() {
                //      public int compare(Dish d1, Dish d2) {
                //          return d1.getCalories() - d2.getCalories();
                //      }
                // }
                //等价的lambda表达式是(d1, d2) -> ((Integer)d1.getCalories()).compareTo(d2.getCalories()
                //可以把d1.getCalories()这一部分看作是使用Function<Dish, Integer>实现：
                // new Function<Dish, Integer>() {
                //      Integer apply(Dish d) {
                //          return d.getCalories();
                //      }
                // }
                //即(Disk d) -> d.getCalories()可简写为Function<Dish, Integer> keyExtractor = Disk::getCalories
                //这样第一个lambda表达式可替换为:(d1, d2) -> keyExtractor.apply(d1).compareTo(keyExtractor.apply(d2))
                //其实这就是Comparator.comparing(Function<T, U>)的实现过程。
                .sorted(Comparator.comparing(Dish::getCalories))
                //映射：Function<Dish, String> Dish -> String
                .map(Dish::getName)
                //.collect(Collectors.toList())
                //遍历：Consumer<Dish>
                .forEach(System.out::println);

        //flatMap();

        reduce();

    }


    private static void reduce() {
        List<Integer> numbers = Arrays.asList(1, 3, 4, 6, 9, 8);
        println(numbers.stream().reduce(10, (a, b) -> a + b));
        println(numbers.stream().reduce(Integer::max).get());


    }


    private static void println(Object o) {
        System.out.println(o);
    }


    private static void flatMap() {
        //将["hello", "world"]转换成'h','e','l','o','w','r','d'
        String result = Stream.of("hello", "world")
                .map(word -> word.split(""))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(Collectors.joining(","));
        println(result);
        //.forEach(Collectors.jo);
    }

    private static List<Dish> init() {
        return Arrays.asList(
                new Dish("pork", false, 800, Dish.Type.MEAT),
                new Dish("beef", false, 700, Dish.Type.MEAT),
                new Dish("chicken", false, 400, Dish.Type.MEAT),
                new Dish("french fries", true, 530, Dish.Type.OTHER),
                new Dish("rice", true, 350, Dish.Type.OTHER),
                new Dish("season fruit", true, 120, Dish.Type.OTHER),
                new Dish("pizza", true, 550, Dish.Type.OTHER),
                new Dish("prawns", false, 300, Dish.Type.FISH),
                new Dish("salmon", false, 450, Dish.Type.FISH));
    }
}

class Dish {
    private final String name;//菜名
    private final boolean vegetarian;//素食标志
    private final int calories;//热量
    private final Type type;//类型

    Dish(String name, boolean vegetarian, int calories, Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }

    String getName() {
        return name;
    }

    public boolean isVegetarian() {
        return vegetarian;
    }

    int getCalories() {
        return calories;
    }

    public Type getType() {
        return type;
    }

    @Override
    public String toString() {
        return name;
    }

    public enum Type {MEAT, FISH, OTHER}
}

